package egovframework.com.utl.sys.ssy.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import egovframework.com.cmm.EgovWebUtil;
import egovframework.com.utl.sys.ssy.service.EgovSynchrnServerService;
import egovframework.com.utl.sys.ssy.service.SynchrnServer;
import egovframework.com.utl.sys.ssy.service.SynchrnServerVO;
import egovframework.rte.fdl.cmmn.AbstractServiceImpl;

/**
 * 개요
 * - 동기화대상 서버에 대한 ServiceImpl 클래스를 정의한다.
 *
 * 상세내용
 * - 동기화대상 서버에 대한 등록, 수정, 삭제, 조회 기능을 제공한다.
 * - 동기화대상 서버의 조회기능은 목록조회, 상세조회로 구분된다.
 * @author lee.m.j
 * @version 1.0
 * @created 28-6-2010 오전 10:44:34
 */
@Service("egovSynchrnServerService")
public class EgovSynchrnServerServiceImpl extends AbstractServiceImpl implements EgovSynchrnServerService{

	@Resource(name="synchrnServerDAO")
	private SynchrnServerDAO synchrnServerDAO;

	/**
	 * 동기화대상 서버를 관리하기 위해 등록된 동기화대상 서버목록을 조회한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 * @return List - 동기화대상 서버 목록
	 */
	public List<SynchrnServerVO> selectSynchrnServerList(SynchrnServerVO synchrnServerVO) throws Exception {
		return synchrnServerDAO.selectSynchrnServerList(synchrnServerVO);
	}

	/**
	 * 동기화대상 서버목록 총 갯수를 조회한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 * @return int - 동기화대상 서버 카운트 수
	 */
	public int selectSynchrnServerListTotCnt(SynchrnServerVO synchrnServerVO) throws Exception {
		return synchrnServerDAO.selectSynchrnServerListTotCnt(synchrnServerVO);
	}

	/**
	 * 등록된 동기화대상 서버의 상세정보를 조회한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 * @return synchrnServerVO - 동기화대상 서버 Vo
	 */
	public SynchrnServerVO selectSynchrnServer(SynchrnServerVO synchrnServerVO) throws Exception {
		return synchrnServerDAO.selectSynchrnServer(synchrnServerVO);
	}

	/**
	 * 등록된 동기화대상 서버의 파일 목록을 조회한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 * @return List<String> - String Type List
	 */
	public List<String> selectSynchrnServerFiles(SynchrnServerVO synchrnServerVO) throws Exception {

		List<String> list = new ArrayList<String>();

		try {
			FTPClient ftpClient =  new FTPClient();
	        ftpClient.setControlEncoding("euc-kr");
	        
		    if (! EgovWebUtil.isIPAddress(synchrnServerVO.getServerIp())) {	// 2011.10.25 보안점검 후속조치
				throw new RuntimeException("IP is needed. (" + synchrnServerVO.getServerIp() + ")");
			    }
		    
			InetAddress host = InetAddress.getByName(synchrnServerVO.getServerIp());

			try {
				ftpClient.connect(host, Integer.parseInt(synchrnServerVO.getServerPort()));
				boolean isLogin = ftpClient.login(synchrnServerVO.getFtpId(), synchrnServerVO.getFtpPassword());
				if(!isLogin) throw new Exception("FTP Client Login Error : \n");

			} catch(SocketException se) {
				System.out.println(se);
				throw new Exception(se);
			} catch(Exception e) {
				System.out.println(e);
				throw new Exception(e);
			}

			FTPFile[] fTPFile = null;

	        try {
	            ftpClient.changeWorkingDirectory(synchrnServerVO.getSynchrnLc());
				fTPFile = ftpClient.listFiles(synchrnServerVO.getSynchrnLc());

				for(int i=0; i<fTPFile.length; i++) {
					if(fTPFile[i].isFile())
				        list.add(fTPFile[i].getName());
				}
			} catch(Exception e) {
				//e.printStackTrace();
				System.out.println(e);	// 2011.10.10 보안점검 후속조치
		    } finally {
			    ftpClient.logout();
			}

		} catch(Exception e) {
			list.add("noList");
		}

		return list;
	}

	/**
	 * 등록된 동기화대상 서버의 파일을 삭제한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 */
	public void deleteSynchrnServerFile(SynchrnServerVO synchrnServerVO) throws Exception {

		FTPClient ftpClient =  new FTPClient();
        ftpClient.setControlEncoding("euc-kr");
        
    	if (!EgovWebUtil.isIPAddress(synchrnServerVO.getServerIp())) {	// 2011.10.25 보안점검 후속조치
    	    throw new RuntimeException("IP is needed. (" + synchrnServerVO.getServerIp() + ")");
    	}
    	
		InetAddress host = InetAddress.getByName(synchrnServerVO.getServerIp());

		ftpClient.connect(host, Integer.parseInt(synchrnServerVO.getServerPort()));
		ftpClient.login(synchrnServerVO.getFtpId(), synchrnServerVO.getFtpPassword());

		FTPFile[] fTPFile = null;

        try {
            ftpClient.changeWorkingDirectory(synchrnServerVO.getSynchrnLc());
			fTPFile = ftpClient.listFiles(synchrnServerVO.getSynchrnLc());

			for(int i=0; i<fTPFile.length; i++) {
				if(synchrnServerVO.getDeleteFileNm().equals(fTPFile[i].getName()))
					ftpClient.deleteFile(fTPFile[i].getName());
			}

			SynchrnServer synchrnServer = new SynchrnServer();
            synchrnServer.setServerId(synchrnServerVO.getServerId());
            synchrnServer.setReflctAt("N");
            synchrnServerDAO.processSynchrn(synchrnServer);

		} catch(Exception e) {
			//e.printStackTrace();
			System.out.println(e);	// 2011.10.10 보안점검 후속조치
	    } finally {
		    ftpClient.logout();
		}
	}

	/**
	 * 등록된 동기화대상 서버의 파일을 다운로드 한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 * @param fileNm - 다운로드 대상 파일
	 */
	public void downloadFtpFile(SynchrnServerVO synchrnServerVO, String fileNm) throws Exception {

		FTPClient ftpClient =  new FTPClient();
        ftpClient.setControlEncoding("euc-kr");
        
    	if (!EgovWebUtil.isIPAddress(synchrnServerVO.getServerIp())) {	// 2011.10.25 보안점검 후속조치
    	    throw new RuntimeException("IP is needed. (" + synchrnServerVO.getServerIp() + ")");
    	}
    	
		InetAddress host = InetAddress.getByName(synchrnServerVO.getServerIp());

		ftpClient.connect(host, Integer.parseInt(synchrnServerVO.getServerPort()));
		ftpClient.login(synchrnServerVO.getFtpId(), synchrnServerVO.getFtpPassword());
		ftpClient.changeWorkingDirectory(synchrnServerVO.getSynchrnLc());

		File downFile = new File(EgovWebUtil.filePathBlackList(synchrnServerVO.getFilePath() + fileNm));
		OutputStream outputStream = null;

		try {
			outputStream = new FileOutputStream(downFile);
			ftpClient.retrieveFile(fileNm, outputStream);
		} catch(Exception e) {
			//e.printStackTrace();
			System.out.println(e);	// 2011.10.10 보안점검 후속조치
		} finally {
			if(outputStream != null) outputStream.close();
		}

		ftpClient.logout();
	}

	/**
	 * 동기화대상 서버정보를 신규로 등록한다.
	 * @param synchrnServer - 동기화대상 서버 model
	 * @param synchrnServerVO    - 동기화대상 서버 VO
	 */
	public SynchrnServerVO insertSynchrnServer(SynchrnServer synchrnServer, SynchrnServerVO synchrnServerVO) throws Exception {
		synchrnServerDAO.insertSynchrnServer(synchrnServer);
		synchrnServerVO.setServerId(synchrnServer.getServerId());
		return synchrnServerDAO.selectSynchrnServer(synchrnServerVO);
	}

	/**
	 * 기 등록된 동기화대상 서버정보를 수정한다.
	 * @param synchrnServer - 동기화대상 서버 model
	 */
	public void updateSynchrnServer(SynchrnServer synchrnServer) throws Exception {
		synchrnServerDAO.updateSynchrnServer(synchrnServer);
	}

	/**
	 * 기 등록된 동기화대상 서버정보를 삭제한다.
	 * @param synchrnServer - 동기화대상 서버 model
	 */
	public void deleteSynchrnServer(SynchrnServer synchrnServer) throws Exception {
		synchrnServerDAO.deleteSynchrnServer(synchrnServer);
	}

	/**
	 * 업로드 파일을 동기화대상 서버들을 대상으로 동기화 처리를 한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 * @return boolean - 성공여부
	 */
	public boolean processSynchrn(SynchrnServerVO synchrnServerVO, File[] uploadFile) throws Exception {

		List<SynchrnServerVO> synchrnServerList = synchrnServerDAO.processSynchrnServerList(synchrnServerVO);
		Iterator<SynchrnServerVO> iterator = synchrnServerList.iterator();
		SynchrnServer synchrnServer = new SynchrnServer();
		boolean reflctAt = false;

		while(iterator.hasNext()) {
			SynchrnServerVO SynchrnServerVo = iterator.next();

			reflctAt = processFtp(SynchrnServerVo.getServerIp(),
					              Integer.parseInt(SynchrnServerVo.getServerPort()),
					              SynchrnServerVo.getFtpId(),
					              SynchrnServerVo.getFtpPassword(),
					              SynchrnServerVo.getSynchrnLc(),
					              synchrnServerVO.getFilePath(),
					              uploadFile);

			synchrnServer.setServerId(SynchrnServerVo.getServerId());
			if(reflctAt)
			    synchrnServer.setReflctAt("Y");
			else
			    synchrnServer.setReflctAt("N");

			synchrnServerDAO.processSynchrn(synchrnServer);
        }

		return true;
	}

	/**
	 * FTP 서버에 있는 화일 목록을 조회한다.
	 * @param serverIp - String
	 * @param port - int
	 * @param user - String
	 * @param password - String
	 * @param synchrnPath - String
	 * @return List - 화일 목록
	 */
    public List<String> getFtpFileList(String serverIp, int port, String user, String password, String synchrnPath) throws Exception {

    	List<String> list = new ArrayList<String>();
		FTPClient ftpClient =  new FTPClient();
        ftpClient.setControlEncoding("euc-kr");
        
    	if (!EgovWebUtil.isIPAddress(serverIp)) {	// 2011.10.25 보안점검 후속조치
    	    throw new RuntimeException("IP is needed. (" + serverIp + ")");
    	}
    	
		InetAddress host = InetAddress.getByName(serverIp);

		ftpClient.connect(host, port);
		ftpClient.login(user, password);

        ftpClient.changeWorkingDirectory(synchrnPath);
        FTPFile[] fTPFile = ftpClient.listFiles(synchrnPath);
        for(int i=0; i<fTPFile.length; i++) {
		    list.add(fTPFile[i].getName());
		}
        return list;
	}

	/**
	 * 동기화 서버들을 대상으로 FTP Upload 처리를 한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 * @return boolean - 성공여부
	 */
	public boolean processFtp(String serverIp, int port, String user, String password, String synchrnPath, String filePath, File[] uploadFile) throws Exception {

	    boolean upload = false;

	    try {
			FTPClient ftpClient =  new FTPClient();
			ftpClient.setControlEncoding("euc-kr");
			
			if (! EgovWebUtil.isIPAddress(serverIp)) {	// 2011.10.25 보안점검 후속조치
				throw new RuntimeException("IP is needed. (" + serverIp + ")");
			}

			InetAddress host = InetAddress.getByName(serverIp);

			ftpClient.connect(host, port);
			if(!ftpClient.login(user, password))
				throw new Exception("FTP Client Login Error : \n");

			if(synchrnPath.length() != 0) ftpClient.changeWorkingDirectory(synchrnPath);

	        FTPFile[] fTPFile = ftpClient.listFiles(synchrnPath);

			FileInputStream fis = null;
	        try {
	        	for(int i=0; i<uploadFile.length; i++) {
	    		    if(uploadFile[i].isFile()) {
	    		    	if(!isExist(fTPFile, uploadFile[i])) {
	    	                fis = new FileInputStream(uploadFile[i]);
	    	                ftpClient.storeFile(synchrnPath+uploadFile[i].getName(), fis);
	    		    	}
	    		    	if (fis != null) { // 2011.11.1 보안점검 후속조치
	    		    		fis.close();
	    		    	}
	    		    }
	        	}

	        	// 업로드 파일 목록에 없는  FTP 서버에 있는 파일을 삭제한다.
	        	fTPFile = ftpClient.listFiles(synchrnPath);
	        	deleteFtpFile(ftpClient, fTPFile, uploadFile);

	        	upload = true;

	        } catch(IOException ex) {
	        	//ex.printStackTrace();
				System.out.println(ex);	// 2011.10.10 보안점검 후속조치
	        } finally {
	            if (fis != null) try { fis.close(); } catch(IOException ignore) {System.out.println("IGNORE: " + ignore);}
	        }
	        ftpClient.logout();

	    } catch(Exception e) {
	    	//e.printStackTrace();
			System.out.println(e);	// 2011.10.10 보안점검 후속조치
	    	upload = false;
	    }

        return upload;
	}

	/**
	 * 동기화 서버에 upload 할 파일이 존재하는지 확인한다.
	 * @param fTPFiles - 동기화대상 서버의 파일 목록
	 * @param targetFile - 동기화대상 파일
	 * @return boolean - 존재여부
	 */
	public boolean isExist(FTPFile[] fTPFiles, File targetFile) throws Exception {

		boolean isExist = false;

        for(int i=0; i<fTPFiles.length; i++) {
        	if(fTPFiles[i].isFile()) {
            	if(fTPFiles[i].getName().equals(targetFile.getName()))
        	        isExist = true;
        	}
		}

		return isExist;
	}

	/**
	 * 동기화 서버의 파일 목록 중 upload 파일 목록에 없는 파일은 삭제한다.
	 * @param fTPFiles - 동기화대상 서버의 파일 목록
	 * @param uploadFile - 업로드 파일 목록
	 * @return boolean - 존재여부
	 */
	public void deleteFtpFile(FTPClient ftpClient, FTPFile[] fTPFiles, File[] uploadFile) throws Exception {

        boolean isExist = false;

		for(int i=0; i<fTPFiles.length; i++) {
			isExist = false;
        	for(int j=0; j<uploadFile.length; j++) {
        		if(fTPFiles[i].isFile()) {
        	        if(fTPFiles[i].getName().equals(uploadFile[j].getName())) {
        	    	    isExist = true;
        	        }
        	    }
            }

        	if(!isExist) {
        		if(fTPFiles[i].isFile()) {
        		    ftpClient.deleteFile(fTPFiles[i].getName());
        		}
        	}
		}
	}

	/**
	 * 업로드 파일의 목록을 조회한다.
	 * @param filePath - 업로드 경로
	 * @return List - 업로드 파일 리스트
	 */
	public List<String> getFileName(String filePath) throws Exception {

		File uploadFile = new File(EgovWebUtil.filePathBlackList(filePath));
        File[] fileList = uploadFile.listFiles();
		List<String> fileArray = new ArrayList<String>();

        for(int i=0; i<fileList.length; i++) {
        	if(fileList[i].isFile()) {
        		fileArray.add(fileList[i].getName());
        	}
		}
        return fileArray;
	}

	/**
	 * 동기화 대상 파일을 업로드 한다.
	 * @param file - 업로드 대상 파일
	 * @param newName - 업로드 대상 파일명
	 * @param stordFilePath - 업로드 경로
	 */
	public void writeFile(MultipartFile multipartFile, String newName, String stordFilePath, SynchrnServerVO synchrnServerVO) throws Exception {

		List<SynchrnServerVO> synchrnServerList = synchrnServerDAO.processSynchrnServerList(synchrnServerVO);
		Iterator<SynchrnServerVO> iterator = synchrnServerList.iterator();
		SynchrnServer synchrnServer = new SynchrnServer();

		InputStream stream = null;
        OutputStream bos = null;

        try {
            stream = multipartFile.getInputStream();
            File cFile = new File(EgovWebUtil.filePathBlackList(stordFilePath));

            if (!cFile.isDirectory())
                cFile.mkdir();

            bos = new FileOutputStream(EgovWebUtil.filePathBlackList(stordFilePath + File.separator + newName));

            int bytesRead = 0;
            byte[] buffer = new byte[2048];

            while ((bytesRead = stream.read(buffer, 0, 2048)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }

            while(iterator.hasNext()) {
            	SynchrnServerVO SynchrnServerVo = iterator.next();
            	synchrnServer.setServerId(SynchrnServerVo.getServerId());
            	synchrnServer.setReflctAt("N");
            	synchrnServerDAO.processSynchrn(synchrnServer);
            }

		} catch (Exception e) {
		    //e.printStackTrace();
		    System.out.println(e);	// 2011.10.10 보안점검 후속조치 finally
		} finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (Exception ignore) {
                	System.out.println("IGNORE: " + ignore);
                }
            }
            if (stream != null) {
                try {
                    stream.close();
                } catch (Exception ignore) {
                	System.out.println("IGNORE: " + ignore);
                }
            }
        }
    }

	/**
	 * 업로드 파일을 삭제한다.
	 * @param synchrnServerVO - 동기화대상 서버 Vo
	 */
	public void deleteFile(String deleteFiles, String stordFilePath, SynchrnServerVO synchrnServerVO) throws Exception {

		List<SynchrnServerVO> synchrnServerList = synchrnServerDAO.processSynchrnServerList(synchrnServerVO);
		Iterator<SynchrnServerVO> iterator = synchrnServerList.iterator();
		SynchrnServer synchrnServer = new SynchrnServer();

		String [] strDeleteFiles = deleteFiles.split(";");

		for(int i=0; i<strDeleteFiles.length;i++) {
			File uploadFile = new File(EgovWebUtil.filePathBlackList(stordFilePath + strDeleteFiles[i]));
			uploadFile.delete();
    	}

        while(iterator.hasNext()) {
        	SynchrnServerVO SynchrnServerVo = iterator.next();
        	synchrnServer.setServerId(SynchrnServerVo.getServerId());
        	synchrnServer.setReflctAt("N");
        	synchrnServerDAO.processSynchrn(synchrnServer);
        }
	}
}